// SPIN.H
// Spin class for a text edit control, with up/down arrows.
// Jason Hood.
// 25 July to 3 August, 1996.
// Modified: 1 to 9 December.

#ifndef _spin_h
#define _spin_h

#include <tws/edit.h>
#include <tws/button.h>

#define ID_EDIT  99995
#define ID_UPTRI 99996
#define ID_DNTRI 99997

#define TriBtnW (SysFont->width*2-1)
#define TriBtnH ((SysFont->height+4)/2)

// This event calls function with one parameter - the keyboard status
#define E_BUTTONDOWNK(ID, function) \
   if (ev->Type == W_NOTIFY && ev->p1 == ID && ev->p2 == 1011) { \
     function(ev->p3); \
     return true; \
   }


class TriButton : public BasicButton {

public:
  TriButton(Window* parent, ControlID ID, int x, int y, int h) :
    BasicButton(parent, ID, x, y, x+TriBtnW-1, y+h-1),
    kbstat(0), timing(false) {}

protected:

  void PaintWindow(int x1, int y1, int x2, int y2);

  void LButtonDown(int x, int y, int key_stat, int timer);
  void LButtonUp(int x, int y, int key_stat);
  void MouseMove(int x, int y, int key_stat, int but_stat);
  void MoveOutside(int x, int y, int key_stat, int but_stat);
  void Timer();

  DECLARE_RESPONSE_TABLE;

  int kbstat;
  bool timing;
};


// This event is queued when the number is changed
#define E_SPINCHANGE(ID, function) \
   if (ev->Type == W_NOTIFY && ev->p1 == ID && ev->p2 == 1012) { \
     function(); \
     return true; \
   }


class Spin : public Window {

public:
  Spin(Window* parent, ControlID ID, const char* title,
       int n, int x, int y, int l);

  void SetNum(int num);
  void SetAdjust(int adjust) {Adjust = adjust;}
  void SetShiftAdjust(int adjust) {ShiftAdjust = adjust;}
  void SetCtrlAdjust(int adjust) {CtrlAdjust = adjust;}
  void SetShiftCtrlAdjust(int adjust) {ShiftCtrlAdjust = adjust;}
  void SetMin(int min) {Min = min >? absMin; SetNum(GetNum());}
  void SetMax(int max) {Max = max <? absMax; SetNum(GetNum());}

  int GetNum() {return atoi(Edit.GetText());}
  int GetAdjust() {return Adjust;}
  int GetShiftAdjust() {return ShiftAdjust;}
  int GetCtrlAdjust() {return CtrlAdjust;}
  int GetShiftCtrlAdjust() {return ShiftCtrlAdjust;}
  int GetMin() {return Min;}
  int GetMax() {return Max;}

  void Select() { parent->SetFocus(this); }

protected:

  int Valid(int num) {return (Min >? num <? Max);}

  void Focus() { Edit.Focus(); }
  void UnFocus() { Edit.UnFocus(); SetNum(GetNum()); }

  int  TestKeys(int kbstat);
  void cmUp(int kbstat);
  void cmDown(int kbstat);

  DECLARE_RESPONSE_TABLE;

  int Min, Max, absMin, absMax,
      Adjust, ShiftAdjust, CtrlAdjust, ShiftCtrlAdjust;
  EditText Edit;
  TriButton Up, Down;
  ControlID spinID;
};


#endif
